/*
Copyright (C) Ariff Ehsan, Abdul Hadi Fikri

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
*/

/*  Author : Ariff Ehsan
 *  Date   : Jan 13, 2010
 */


#include <system.h>
#include <keypad44/keypad44.h>


/**
 *  Local variables
 */

timer_t keypad44_timer;

uint8_t keypad44_state[4][4];

void (*keypad44_event)(uint8_t x, uint8_t y, uint8_t state);

/**
 *  Local prototype function
 */
void KEYPAD44_TIMER_run(void);
void KEYPAD44_update(uint8_t x, uint8_t y, BOOL state);

void KEYPAD44_defaultEvent(uint8_t x, uint8_t y, uint8_t state);


/******************************************************************************
 *                           FUNCTION IMPLEMENTATION
 */

void KEYPAD44_init(void) {
	
	KEYPAD44_DDR = 0x0f; // msb - key in, lsb - key out
	KEYPAD44_PORT = 0;
	
	TIMER_reg(&keypad44_timer, KEYPAD44_TIMER_run);
	TIMER_startPeriodic(&keypad44_timer, KEYPAD44_SCAN_RATE);
	
	uint8_t i, j;
	
	for (i = 0; i < 4; i++) {
		
		for (j = 0; j < 4; j++)
			keypad44_state[i][j] = KEYPAD44_STATE_RELEASED;
	}
	
	keypad44_event = KEYPAD44_defaultEvent;
}


void KEYPAD44_reg(void (*event)(uint8_t x, uint8_t y, uint8_t state)) {
	
	if (event != NULL)
		keypad44_event = event;
}


void KEYPAD44_TIMER_run(void) {
	
	uint8_t x, y;
	
	for (x = 0; x < 4; x++) {
		
		KEYPAD44_PORT &= 0xf0;
		KEYPAD44_PORT |= (1 << x);
		
		for (y = 0; y < 4; y++) {
			
			uint8_t i = KEYPAD44_PIN & ((1 << y) << 4);
			
			if (i > 0)
				KEYPAD44_update(x, y, TRUE);
			else
				KEYPAD44_update(x, y, FALSE);
		}
	}
}


void KEYPAD44_update(uint8_t x, uint8_t y, BOOL state) {
	
	switch(keypad44_state[x][y]) {
		
	case KEYPAD44_STATE_RELEASED:
		
		if (state)
			keypad44_state[x][y] = KEYPAD44_STATE_PUSHING;
		
		break;
		
	case KEYPAD44_STATE_PUSHING:
		
		keypad44_state[x][y] = KEYPAD44_STATE_PUSHED;
		keypad44_event(x, y, KEYPAD44_STATE_PUSHED);
		
		break;
		
	case KEYPAD44_STATE_PUSHED:
		
		if (!state)
			keypad44_state[x][y] = KEYPAD44_STATE_RELEASING;
		
		break;
		
	case KEYPAD44_STATE_RELEASING:
		
		keypad44_state[x][y] = KEYPAD44_STATE_RELEASED;
		keypad44_event(x, y, KEYPAD44_STATE_RELEASED);
		
		break;
	}
}


void KEYPAD44_defaultEvent(uint8_t x, uint8_t y, uint8_t state) {
}
